﻿// --------------------------------------------------------------------------------------------------------------------
// <summary>
//   MsmqEnqueueStep.cs
// </summary>
// --------------------------------------------------------------------------------------------------------------------
namespace TRlib.BizUnit.CustomSteps
{
    using System;
    using System.Collections;
    using System.Collections.Generic;
    using System.Configuration;
    using System.IO;
    using System.Messaging;
    using System.Text;
    using System.Xml;
    using global::BizUnit;

    /// <summary>
    /// Queues a file to a message queue 
    /// </summary>
    /// <remarks>
    /// The following shows an example of the Xml representation of this test step.
    /// 
    /// <code escaped="true">
    ///  <TestStep assemblyPath="" typeName="MsmqEnqueueStep">
    ///   <MessageData>
    ///    <MessagePath type="xml">.\Data\MessageInstances\Policy_v1_0-instance - New Account.xml</MessagePath>
    ///   </MessageData>
    ///   <QueueName>Policies.Hub.Input</QueueName>
    ///   <UseTransactions>true</UseTransactions>
    ///  </TestStep>
    /// </code>
    ///    
    ///    <list type="table">
    ///        <listheader>
    ///            <term>Tag</term>
    ///            <description>Description</description>
    ///        </listheader>
    ///        <item>
    ///            <term>MessageData</term>
    ///            <description>Container for MessagePath node. Currently only supports single file.</description>
    ///        </item>
    ///        <item>
    ///            <term>MessagePath</term>
    ///            <description>Contains file path</description>
    ///        </item>
    ///        <item>
    ///            <term>MessagePath/@type</term>
    ///            <description>xml or text</description>
    ///        </item>
    ///        <item>
    ///            <term>QueueName</term>
    ///            <description>Name of queue (note not path). Currently only private queues supported</description>
    ///        </item>
    ///        <item>
    ///            <term>UseTransactions</term>
    ///            <description>true or false</description>
    ///        </item>
    ///    </list>
    /// </remarks>
    public class MsmqEnqueueStep : ITestStep
    {
        #region ITestStep Members
        public void Execute(System.Xml.XmlNode testConfig, Context context)
        {
            // Get queue address
            string queueName = context.ReadConfigAsString(testConfig, "QueueName");
            string serverName;
            
            if (testConfig.SelectSingleNode("ServerName") != null)
            {
                serverName = context.ReadConfigAsString(testConfig, "ServerName");
            }
            else
            {
                serverName = ConfigurationManager.AppSettings["ServerName"];
            }

            string queuePath = string.Format(@"FormatName:DIRECT=OS:{0}\Private$\{1}", serverName, queueName);

            // Get message body
            string messageBody = this.BuildMessageBody(
                    testConfig.SelectSingleNode("MessageData/MessagePath/@type").InnerText,
                    testConfig.SelectSingleNode("MessageData/MessagePath").InnerText);

            // use transactions?
            bool useTrans = context.ReadConfigAsBool(testConfig, "UseTransactions");

            // Send message
            byte[] buffer = System.Text.UTF8Encoding.UTF8.GetBytes(messageBody);
            if (buffer.Length > 0)
            {
                Message msg = new Message();
                msg.BodyStream = new MemoryStream(buffer);
                msg.Priority = MessagePriority.Normal;
                msg.Recoverable = true;
                msg.UseDeadLetterQueue = true;

                using (MessageQueue q = new MessageQueue(queuePath))
                {
                    if (useTrans)
                    {
                        q.Send(msg, MessageQueueTransactionType.Single);
                    }
                    else
                    {
                        q.Send(msg, MessageQueueTransactionType.None);
                    }
                }
            }

            context.LogInfo(string.Format("Message sent. Body: {0} queue: {1}", messageBody, queuePath));
        }
        #endregion

        protected string BuildMessageBody(string format, string path)
        {
            switch (format.ToLower())
            {
                case "xml":
                    XmlDocument doc = new XmlDocument();
                    doc.Load(path);
                    return doc.OuterXml;
                case "text":
                    StreamReader reader = new StreamReader(path);
                    string text = reader.ReadToEnd();
                    reader.Close();
                    return text;
                default:
                    return String.Empty;
            }
        }
    }
}
